#ifndef SCRIPTING_H
#define SCRIPTING_H

#include <map>
#include <set>
#include "M_Code_exception.h"
#include "globals.h"
#include "manager.h"
#include "menuitemsmanager.h"
#include <wx/intl.h>

struct SquirrelError;
class ScriptingManager : public Mgr<ScriptingManager>, public wxEvtHandler {
    friend class Mgr<ScriptingManager>;
    wxCriticalSection cs;
  public:
    struct TrustedScriptProps {
      bool permanent;
      wxUint32 crc;
    };
    typedef std::map<wxString, TrustedScriptProps> TrustedScripts;
    bool LoadScript( const wxString& filename );
    bool LoadBuffer( const wxString& buffer, const wxString& debugName = _T( "CommandLine" ) );
    wxString LoadBufferRedirectOutput( const wxString& buffer );
    wxString GetErrorString( SquirrelError* exception = nullptr, bool clearErrors = true );
    void DisplayErrors( SquirrelError* exception = nullptr, bool clearErrors = true );
    void InjectScriptOutput( const wxString& output );
    int Configure();
    bool RegisterScriptPlugin( const wxString& name, const wxArrayInt& ids );
    bool RegisterScriptMenu( const wxString& menuPath, const wxString& scriptOrFunc, bool isFunction );
    bool UnRegisterScriptMenu( const wxString& menuPath );
    bool UnRegisterAllScriptMenus();
    bool IsScriptTrusted( const wxString& script );
    bool IsCurrentlyRunningScriptTrusted();
    void TrustScript( const wxString& script, bool permanently );
    void TrustCurrentlyRunningScript( bool permanently );
    bool RemoveTrust( const wxString& script );
    void RefreshTrusts();
    const TrustedScripts& GetTrustedScripts();
    ScriptingManager& operator=( M_Code_unused const ScriptingManager& rhs ) {
      m_Throw( _T( "Can't assign a ScriptingManager* !!!" ) );
      return *this;
    }
  private:
    ScriptingManager( M_Code_unused const ScriptingManager& rhs );
    void OnScriptMenu( wxCommandEvent& event );
    void OnScriptPluginMenu( wxCommandEvent& event );
    void RegisterScriptFunctions();
    ScriptingManager();
    ~ScriptingManager();
    TrustedScripts m_TrustedScripts;
    struct MenuBoundScript {
      wxString scriptOrFunc;
      bool isFunc;
    };
    typedef std::map<int, MenuBoundScript> MenuIDToScript;
    MenuIDToScript m_MenuIDToScript;
    bool m_AttachedToMainWindow;
    wxString m_CurrentlyRunningScriptFile;
    typedef std::set<wxString> IncludeSet;
    IncludeSet m_IncludeSet;
    MenuItemsManager m_MenuItemsManager;
    DECLARE_EVENT_TABLE()
};

typedef char SQChar;
void PrintSquirrelToWxString( wxString& msg, const SQChar* s, va_list& vl );

#endif
